home *** CD-ROM | disk | FTP | other *** search
- /* Gravity.c
- **
- ** Copyright 1995, mFactory, Inc.
- ** All rights reserved.
- */
-
- #include "Gravity.h"
- #include <math.h>
-
- #define kActivatePopup 6 // DITL indices
- #define kTerminatePopup 8
- #define kGravConstField 11
-
- #define kMassAttrib ((CompID *) "mass\0\0\0\0\0\0\0\0\0\0\0\0") // attributes
- #define kResVectorAttrib ((CompID *) "resultantvector\0")
-
- #define kTimePeriod 10 // milliseconds
-
-
- /* Initial entry point
- */
-
- MCompMainFuncDcl MCompMainName(MInitInfo *initInfo)
- {
- MDefineComponent(GravitySrvComp, kMCanDragOff);
- MInheritClass(MComponent, kMCompNumProcs, kMBaseCompSlot);
-
- // MComponent methods we must override
-
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompConstructor, MCompConstructor);
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompCopy, MCompCopy);
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompCopyConstructor, MCompCopyConstructor);
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompDestructor, MCompDestructor);
-
- // MComponent methods we choose to override
-
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompEditorOpen, MCompEditorOpen);
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompEditorAccept, MCompEditorAccept);
-
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompGetSaveInfo, MCompGetSaveInfo);
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompSaveComponent, MCompSaveComponent);
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompRestoreComponent, MCompRestoreComponent);
-
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompProcessMessage, MCompProcessMessage);
-
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompGetAttribute, MCompGetAttribute);
-
- MDefineMethod(kGravitySrvSlot, kMBaseCompSlot, kMCompAdaptIDs, MCompAdaptIDs);
-
- // Introduce our own methods
-
- MDefineMethod(kGravitySrvSlot, kGravitySrvSlot, kGravitySrvTask, GravitySrvTask);
-
- MConnectCommonServices(initInfo);
-
- MEndComponentDef;
- }
-
-
- /* Initialize component
- */
-
- static MErr MCompConstructor(GravitySrvComp *self, MObjectRef *mRef)
- {
- MInitEvent(self->f_enableEvent, kMParentEnabled, 0);
- MInitEvent(self->f_disableEvent, kMNone, 0);
- MInitDouble(self->f_constant, 1.0);
- return kMNoCompErr;
- }
-
-
- /* Copy component data
- */
-
- static MErr MCompCopy(GravitySrvComp *self, GravitySrvComp *previousSelf)
- {
- MCopyEvent(self->f_enableEvent, previousSelf->f_enableEvent);
- MCopyEvent(self->f_disableEvent, previousSelf->f_disableEvent);
- MCopyDouble(self->f_constant, previousSelf->f_constant);
- return kMNoCompErr;
- }
-
-
- /* Copy component
- */
-
- static MErr MCompCopyConstructor(GravitySrvComp *self, GravitySrvComp *previousSelf, MObjectRef *mRef)
- {
- MCompConstructor(self, mRef);
- return MCompCopy(self, previousSelf);
- }
-
-
- /* Dispose component
- */
-
- static MErr MCompDestructor(GravitySrvComp *self)
- {
- MDisposeEvent(self->f_enableEvent);
- MDisposeEvent(self->f_disableEvent);
- MDisposeDouble(self->f_constant);
- return kMNoCompErr;
- }
-
-
- /* Open component dialog
- */
-
- static MErr MCompEditorOpen(GravitySrvComp *self, void *editor, short editorType)
- {
- if ( editorType == kMDialogEditorType ) {
- MSetEditorItem(editor, kActivatePopup, (MDataType *) &self->f_enableEvent);
- MSetEditorItem(editor, kTerminatePopup, (MDataType *) &self->f_disableEvent);
- MSetEditorItem(editor, kGravConstField, (MDataType *) &self->f_constant);
- return kMNoCompErr;
- } else
- return kMUnableToComplyCompErr;
- }
-
-
- /* Close component dialog
- */
-
- static MErr MCompEditorAccept(GravitySrvComp *self, void *editor)
- {
- MGetEditorItem(editor, kActivatePopup, (MDataType *) &self->f_enableEvent);
- MGetEditorItem(editor, kTerminatePopup, (MDataType *) &self->f_disableEvent);
- MGetEditorItem(editor, kGravConstField, (MDataType *) &self->f_constant);
- return kMNoCompErr;
- }
-
-
- /* Provide save information
- */
-
- static MErr MCompGetSaveInfo(GravitySrvComp *self, MFileIOServ *file, long saveInfo, short *rev, long *len)
- {
- long valueSize;
-
- MSizeOfValue(file, &self->f_enableEvent, &valueSize);
- *len = valueSize;
- MSizeOfValue(file, &self->f_disableEvent, &valueSize);
- *len += valueSize;
- MSizeOfValue(file, &self->f_constant, &valueSize);
- *len += valueSize;
-
- *rev = kGravitySrvRev;
- return kMNoCompErr;
- }
-
-
- /* Save component
- */
-
- static MErr MCompSaveComponent(GravitySrvComp *self, MFileIOServ *file, long saveInfo)
- {
- MWriteValue(file, &self->f_enableEvent);
- MWriteValue(file, &self->f_disableEvent);
- MWriteValue(file, &self->f_constant);
-
- return kMNoCompErr;
- }
-
-
- /* Restore component
- */
-
- static MErr MCompRestoreComponent(GravitySrvComp *self, MFileIOServ *file, long saveInfo, short rev)
- {
- if ( rev == kGravitySrvRev ) {
- MReadValue(file, &self->f_enableEvent);
- MReadValue(file, &self->f_disableEvent);
- MReadValue(file, &self->f_constant);
- return kMNoCompErr;
- }
- else
- return kMUnableToComplyCompErr;
- }
-
-
- /* Process incoming message
- */
-
- static MErr MCompProcessMessage(GravitySrvComp *self, MMessagePtr message)
- {
- if ( MDetectMessage(message, self->f_enableEvent) ) {
- short i, j;
-
- MRegisterGService(self, self, kMGeneralServiceKey);
- MPostCTimeTask(self, nil, kTimePeriod, kGravitySrvSlot, kGravitySrvTask);
- for (i=0; i<20; i++)
- for ( j=0; j<20; j++) {
- self->f_table[i][j].f_x = 0.0;
- self->f_table[i][j].f_y = 0.0;
- }
- return kMNoCompErr;
- }
- else if ( MDetectMessage(message, self->f_disableEvent) || MDetectDisableMessage(message) ) {
- MKillCTimeTask(self, nil);
- MUnregisterGService(self, self);
- return kMNoCompErr;
- }
- else
- return kMUnableToComplyCompErr;
- }
-
-
- /* Get component attribute
- */
-
- static MErr MCompGetAttribute(GravitySrvComp *self, MomID attribName, MDataType *selector, MDataType *dataValue)
- {
- if ( MCmpMomID(attribName, kMEventsAttrib) && selector &&
- selector->f_type.f_type == kMInteger ) {
- switch (selector->f_integer.f_value & ~kMEventMask)
- {
- case kMEventExecute:
- if ( (selector->f_integer.f_value & kMEventMask) == 1 ) {
- MCopyEvent(dataValue->f_event, self->f_enableEvent);
- return kMNoCompErr;
- }
- else
- return kMUnableToComplyCompErr;
-
- case kMEventTerminate:
- if ( (selector->f_integer.f_value & kMEventMask) == 1 ) {
- MCopyEvent(dataValue->f_event, self->f_disableEvent);
- return kMNoCompErr;
- }
- else
- return kMUnableToComplyCompErr;
-
- default:
- return kMUnableToComplyCompErr;
- }
- }
- else
- return kMUnableToComplyCompErr;
- }
-
-
- /* Adjust project-specific IDs
- */
-
- static MErr MCompAdaptIDs(GravitySrvComp *self, MObjectPtr *sourceStore, MObjectPtr *targetStore)
- {
- MTranslateID(kMTranslateEventID, sourceStore, targetStore, (MDataType *) &self->f_enableEvent);
- MTranslateID(kMTranslateEventID, sourceStore, targetStore, (MDataType *) &self->f_disableEvent);
- return kMNoCompErr;
- }
-
-
- /* Gravity service task
- */
-
- static MErr GravitySrvTask(GravitySrvComp *self, MTInfo *tinfo)
- {
- short i, j, numClients;
- MDataType dataVector, dataPosition, dataSize, dataMass;
- MSelf *client1, *client2;
-
- double mass1, mass2, force, magnitude;
- double period, x, y, tempX, tempY;
- double midX, midY;
-
- double posA_PNTX, posA_PNTY, posB_PNTX, posB_PNTY;
-
- PLPoint size1, size2;
-
- MInitVector2D(dataVector.f_vector, 0.0, 0.0);
- MInitPoint2D(dataPosition.f_point, 0, 0);
- MInitPoint2D(dataSize.f_point, 0, 0);
- MInitDouble(dataMass.f_double, 0.0);
-
- MGetNumClients(self, &numClients);
-
- if ( numClients > 1 && numClients < 21 ) {
-
- // build a table of forces between all bodies
-
- for (i = 0; i < numClients; i++) {
- MGetNthClient(self, i, &client1);
- if ( MError() != kMNoCompErr )
- return MError();
-
- MGetAttribute(client1, kMPositionAttrib, 0, &dataPosition); // get info from 1st body
- posA_PNTX = dataPosition.f_vector.f_angle;
- posA_PNTY = dataPosition.f_vector.f_magnitude;
- MGetAttribute(client1, kMSizeAttrib, 0, &dataSize);
- size1 = dataSize.f_point.f_value;
- MGetAttribute(client1, kMassAttrib, 0, &dataMass);
- mass1 = dataMass.f_double.f_value;
-
- midX = posA_PNTX + (double) size1.PNTX / 2.0;
- midY = posA_PNTY + (double) size1.PNTY / 2.0;
-
- for (j = 0; j < i; j++) {
- MGetNthClient(self, j, &client2);
- if ( MError() != kMNoCompErr )
- return MError();
-
- MGetAttribute(client2, kMPositionAttrib, 0, &dataPosition); // get info from 2nd body
- posB_PNTX = dataPosition.f_vector.f_angle;
- posB_PNTY = dataPosition.f_vector.f_magnitude;
- MGetAttribute(client2, kMSizeAttrib, 0, &dataSize);
- size2 = dataSize.f_point.f_value;
- MGetAttribute(client2, kMassAttrib, 0, &dataMass);
- mass2 = dataMass.f_double.f_value;
-
- x = (posB_PNTX + (double) size2.PNTX / 2.0) - midX;
- y = (posB_PNTY + (double) size2.PNTY / 2.0) - midY;
- period = x*x + y*y;
- magnitude = sqrt(period); // calculate distance between bodies
-
- if ( magnitude && mass1 && mass2 ) { // distance plus both masses must exceed zero
-
- force = self->f_constant.f_value * mass1 * mass2 / period; // calculate force
-
- tempX = x / magnitude * force;
- tempY = y / magnitude * force;
-
- // calculate acceleration vector originiating from client1
- self->f_table[i][j].f_x = tempX / mass1;
- self->f_table[i][j].f_y = tempY / mass1;
-
- // the acceleratrion vector originating from client2...
- // ...is the inverse of that from client1
- self->f_table[j][i].f_x = -tempX / mass2;
- self->f_table[j][i].f_y = -tempY / mass2;
- }
- else {
- self->f_table[i][j].f_x = self->f_table[i][j].f_y = 0.0;
- self->f_table[j][i].f_x = self->f_table[j][i].f_y = 0.0;
- }
- }
- }
-
- // add all acceleration vectors acting on each body
-
- for (i = 0; i < numClients; i++) {
- MGetNthClient(self, i, &client1);
- if ( MError() != kMNoCompErr )
- return MError();
-
- x = y = 0.0;
- for (j = 0; j < numClients; j++)
- if ( j != i ) {
- x = x + self->f_table[i][j].f_x;
- y = y + self->f_table[i][j].f_y;
- }
-
- dataVector.f_vector.f_angle = x;
- dataVector.f_vector.f_magnitude = y;
- MSetAttribute(client1, kResVectorAttrib, 0, &dataVector);
- }
- return kMNoCompErr;
-
- } else
- return kMUnableToComplyCompErr;
- }
-